package com.umfwechat.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.umfwechat.common.prop.UmfPropModel;


/**
 * 获取二维码工具类
 * @author xuhuibing
 *
 */

public class WexinQrCodeUtil {
	private static Logger logger = LoggerFactory.getLogger(WexinQrCodeUtil.class);
	public static final String TOKENURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	
	public static String getXcxAccessToken(){
		//先从缓存中获取
		String xcxAccessToken =null;
		try {
			xcxAccessToken = RedisUtil.get("XCX_ACCESS_TOKEN");
		} catch (Exception e) {
			logger.error("缓存服务器异常",e);
			e.printStackTrace();
		}
		//如果缓存中没有获取成功，或者获取失败了，就从重新获取一份新的
		if(xcxAccessToken==null){
			String APPID=UmfPropModel.INSTANCE.getPropValue("xcxAppid");
			String APPSECRET=UmfPropModel.INSTANCE.getPropValue("xcxSecret");
			logger.info("appid和secret都获取到了");
			String requestUrl = TOKENURL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
			HttpGet get = new HttpGet(requestUrl);
			try {
				HttpResponse response = client.execute(get);
				xcxAccessToken = EntityUtils.toString(response.getEntity());
				logger.error("请求微信服务器出参"+xcxAccessToken);
			} catch (Exception e) {
				logger.error("请求微信服务器异常",e);
				e.printStackTrace();
			}
			//设置access_token 有效期60,60,2
			try {
				RedisUtil.set("XCX_ACCESS_TOKEN", 60*60*2, xcxAccessToken);
			} catch (Exception e) {
				logger.error("缓存服务器异常",e);
				e.printStackTrace();
			}
		}
		return xcxAccessToken;
	}
	
	static HttpClient client;

	public WexinQrCodeUtil() {
		client = HttpClients.createDefault();
	}
	
	/**
	 * 获取访问token
	 */
	public static String reqToken() {
		String token = RedisUtil.get("XCX_ACCESS_TOKEN");
		if(token == null){
			String APPID = PropertyUtil.getStrValue("umfWeChatPlat_appConf.properties","xcxAppid", ""); 
			String APPSECRET = PropertyUtil.getStrValue("umfWeChatPlat_appConf.properties","xcxSecret", ""); 
			String tokenUrl = TOKENURL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
			HttpGet get = new HttpGet(tokenUrl);
			try {
				HttpResponse response = client.execute(get);
				String content = EntityUtils.toString(response.getEntity());
				token = content;
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			//设置access_token 有效期
			RedisUtil.set("XCX_ACCESS_TOKEN", 3600, token);
		}
		return token;
	}	
	/**
	 * 获取小程序码
	 * 
	 * @param token
	 * @return
	 */
	public static String getwxacode(String path,String token) {
		//生成access_token
		String weixinQrUrl = PropertyUtil.getStrValue("umfWeChatPlat_appConf.properties", "weixin.qr.url", "");
		HttpPost post = new HttpPost(weixinQrUrl + token);
		String imgUrl = PropertyUtil.getStrValue("umfWeChatPlat_appConf.properties","saasPlat.comp.uploadPath", "");	//获取二微碼保存地址
		String url=imgUrl + UUID.randomUUID().toString() + ".jpg";
		try {
			JSONObject obj = new JSONObject();
			obj.put("path", path);
			obj.put("width", 430);
			StringEntity entity = new StringEntity(obj.toString());
			post.setEntity(entity);
			HttpResponse reponse = client.execute(post);
			byte[] content = EntityUtils.toByteArray(reponse.getEntity());
			File files = new File(imgUrl);
			if (!files.exists()) {
				files.mkdirs();
			}
			File ff = new File(url);
			FileOutputStream fw = new FileOutputStream(ff);
			fw.write(content, 0, content.length);
			fw.flush();
			fw.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			post.releaseConnection();
		}
		return url;
	}
	
	/**     
	 * 生成二维码图片 不存储 直接以流的形式输出到页面    
	 * @param content     
     * @param response    
     */    
	@SuppressWarnings("unchecked")
	public static void encodeQrcode(String content,HttpServletResponse response,String filename) throws Exception{        
		if(StringUtil.isEmpty(content)){
			return;        
		}
		MultiFormatWriter multiFormatWriter = new MultiFormatWriter();        
		Hashtable hints = new Hashtable();        
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //设置字符集编码类型        
		hints.put(EncodeHintType.MARGIN, 0); //设置余白
		BitMatrix bitMatrix = null;        
		try {            
			bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 300, 300,hints);            
			BufferedImage image = toBufferedImage(bitMatrix);            //输出二维码图片流            
			response.setContentType("image/png");//设置http传输模式	
			response.setHeader("Content-Disposition", "inline;filename=" + filename + ".png");//设置合同名称及属性
			response.setCharacterEncoding("UTF-8");//设置编码为utf8
			try {                
				ImageIO.write(image, "png", response.getOutputStream());    
			} catch (IOException e) {                
				e.printStackTrace();            
			}
		} catch (WriterException e1) {            
			e1.printStackTrace();        
		}
	}
	
	private static BufferedImage toBufferedImage(BitMatrix matrix) {
		int WHITE = 0xFFFFFFFF;      
		int BLACK = 0xFF000000; 
		int width = matrix.getWidth();         
		int height = matrix.getHeight();        
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);         
		for (int x = 0; x < width; x++) {           
			for (int y = 0; y < height; y++) {             
				image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);           
				}         
			}         
		return image;    
	}
}
